/*
 * Su-yun Information Technology, Co.,Ltd CONFIDENTIAL
 *
 * (C) Copyright Su-yun Information Technology, Co.,Ltd. 2021 All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains the property of
 * Su-yun Information Technology, Co.,Ltd. The intellectual property herein
 * are protected by trade secret, patent law or copyright law. Dissemination
 * of this information or reproduction of this material is strictly forbidden
 * unless prior written permission is obtained from Su-yun Information Technology.
 *
 * https://suyunplat.com/
 *
 */
package com.xtiim.battery.discharge.serial;

import com.xtiim.battery.discharge.event.DefaultEventPublisher;
import com.xtiim.battery.discharge.event.EventPublisher;
import com.xtiim.battery.discharge.protocal.event.PortReceiveFailureEvent;
import com.xtiim.battery.discharge.protocal.event.ResponseReceivedEvent;
import com.xtiim.battery.discharge.util.ByteUtil;
import com.xtiim.battery.discharge.util.SerialPortUtil;
import lombok.extern.slf4j.Slf4j;
import purejavacomm.SerialPort;
import purejavacomm.SerialPortEvent;
import purejavacomm.SerialPortEventListener;

/**
 * Serial port event listener
 *
 */
@Slf4j
public class DefaultPortEventLister implements SerialPortEventListener {
    private SerialPort port;

    private EventPublisher eventPublisher = DefaultEventPublisher.getInstance();

    public DefaultPortEventLister(SerialPort port) {
        this.port = port;
    }

    @Override
    public void serialEvent(SerialPortEvent event) {
            switch (event.getEventType()) {
                case SerialPortEvent.DATA_AVAILABLE:
                    try {
                        byte[] bytes = SerialPortUtil.readFromPort(port);
                        log.debug("[Received data] port: {}, bytes: {}", port.getName(), ByteUtil.byte2hex(bytes));

                        ResponseReceivedEvent responseReceivedEvent = new ResponseReceivedEvent(this, port.getName(), bytes);
                        eventPublisher.publishEvent(responseReceivedEvent);
                    } catch (Throwable e) {
                        log.error("Error occurs in reading from port. msg: {}", e.getMessage());
                        eventPublisher.publishEvent(new PortReceiveFailureEvent(this, port.getName()));
                    }
                    break;

                case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
                    log.debug("Output buffer is cleared.");
                    break;

                case SerialPortEvent.CTS:
                    log.debug("To-send data is cleared.");
                    break;

                case SerialPortEvent.DSR:
                    log.debug("To-send data is ready.");
                    break;

                case SerialPortEvent.RI:
                    break;

                case SerialPortEvent.CD:
                    break;

                // overflow error
                case SerialPortEvent.OE:
                    log.error("Overflow error.");
                    break;

                // parity error
                case SerialPortEvent.PE:
                    log.error("Parity error");
                    break;

                // frame error
                case SerialPortEvent.FE:
                    log.error("Frame error");
                    break;

                case SerialPortEvent.BI:
                    log.error("Communication broken.");
                    break;

                default:
                    break;
            }
    }
}
